import LOG4J from "@/common/utils/Log4j";
import getProtocolMethodsByType from "../js_sdk/bluetooth/protocol/index.js";
import {
	response as analysis
} from "../js_sdk/bluetooth/protocol/yongXin.js";
import {
	setWithExpiration,
	getWithExpiration
} from "@/js_sdk/utils/expiration.js";
import {
	batchSaveRingData
} from "@/api/ring/report.js";
import {
	saveDeviceInfo
} from "@/api/ring/bind.js";
import {
	deepClone,
	getStepLength,
	conversionDistanceBySteps,
	conversionCalorieBySteps,
	waiting
} from "@/js_sdk/utils/utils.js";
import SqLiteData from "@/js_sdk/sqLite/data.js";
import SqlLiteAnalysis from "@/js_sdk/sqLite/analysis.js";
import dayjs from "dayjs";

const log4j = LOG4J.getLogCat("BluetoothManagerStore");
log4j.log("这里是戒指数据上报vuex");

const protocol = getProtocolMethodsByType();

const yxQueueIll = ["period", "time", "version", "version", "battery", "battery", "data", "time"];

const yxQueue = [
	() => protocol.setPeriod(60 * 60),
	() => protocol.getTime(),
	() => protocol.getSoftVersion(),
	() => protocol.getHardVersion(),
	() => protocol.getBatteryLevel(),
	() => protocol.getBatteryCharing(),
	(ts) => protocol.getHistoryData(true, ts),
	() => protocol.setTime(),
];

const state = {
	domDataUsedByGuideConfig: {

	},
	ring: {
		name: "",
		deviceId: "",
		mac: "",
		customName: "",
		ringType: "",
	},
	ringTime: {
		timestamp: "",
		timeZone: "",
		date: "",
	},
	version: {
		softwareVersion: "",
		hardwareVersion: "",
	},
	battery: {
		batteryLevel: 100,
		batteryCharging: false,
	},
	heartRate: {
		wear: "",
		wearDescription: "",
		heartRate: "",
		hrv: "",
		press: "",
		progress: 0,
	},

	bloodOxygen: {
		wear: "",
		wearDescription: "",
		bloodOxygen: "",
		progress: 0,
	},

	temperature: "",

	histories: [],

	hexArr: [],

	memory: {
		total: "",
		used: "",
		all: "",
		unUpload: "",
	},

	notifyData: {
		heart: {
			heartRate: "",
			hrv: "",
			press: "",
			temperature: "",
			needAnswer: false,
		},
		blood: {
			heartRate: "",
			bloodOxygen: "",
			temperature: "",
			needAnswer: false,
		},
		battery: {
			batteryLevel: "",
			needAnswer: false,
		},
		fault: {
			reason: "",
			description: "",
			needAnswer: false,
		},
	},

	lastUpdateTime: {
		lastHeartbeatTime: 0,
		lastBloodOxTime: 0,
		lastStepsTime: 0,
		lastPressTime: 0,
		lastSleepTime: 0,
		lastTemperatureTime: 0,
	},

	period: 30,

	syncLoading: false,
	syncProgress: 0,

	queryIndex: -1,

	receiveTimeout: null,

	sqLiteList: [],
	sqLiteAnaList: [],
};

const getters = {
	battery: (state) => state.battery,
	notifyBattery: (state) => state.notifyData.battery,
	getSyncLoading: (state) => state.syncLoading,
	getSyncProgress: (state) => state.syncProgress,
	name: (state) => state.ring.name,
	mac: (state) => state.ring.mac,
	ring: (state) => state.ring,
	domDataUsedByGuideConfig: (state) => state.domDataUsedByGuideConfig
};

const mutations = {
	SET_DOM_DATA_USERD_BY_GUIDE_CONFIG(state, da) {
		state.domDataUsedByGuideConfig = da
	},
	SET_LAST_UPDATE_TIME(state, updateTime) {
		const {
			lastHeartbeatTime,
			lastBloodOxTime,
			lastStepsTime,
			lastPressTime,
			lastSleepTime,
			lastTemperatureTime
		} = updateTime;
		state.lastUpdateTime = {
			lastHeartbeatTime,
			lastBloodOxTime,
			lastStepsTime,
			lastPressTime,
			lastSleepTime,
			lastTemperatureTime,
		};

		console.log("提交了⏰⏰⏰⏰⏰", state.lastUpdateTime);
	},
	SET_QUERY_INDEX(state, index) {
		if (index >= yxQueue.length) return;
		state.queryIndex = index;
	},
	SET_SYNC_PROGRESS(state, progress) {
		state.syncProgress = progress;
	},
	SET_SYNC_LOADING(state, loading) {
		state.syncLoading = loading;
	},
	SET_RING(state, ring) {
		state.ring = Object.assign(state.ring, ring);
	},
	SET_TIME(state, ringTime) {
		state.ringTime = Object.assign(state.ringTime, ringTime);
	},

	SET_VERSION(state, version) {
		if (version.softwareVersion) {
			state.version.softwareVersion = version.softwareVersion;
		}
		if (version.hardwareVersion) {
			state.version.hardwareVersion = version.hardwareVersion;
		}
	},

	SET_BATTERY(state, battery) {
		state.battery = Object.assign({
			...state.battery
		}, {
			...battery
		});
	},
	SET_HEARTRATE_HRV_PRESS(state, heartRate) {
		state.heartRate = Object.assign({
			...state.heartRate
		}, {
			...heartRate
		});
	},

	SET_BLOOD(state, blood) {
		state.bloodOxygen = Object.assign({
			...state.bloodOxygen
		}, {
			...blood
		});
		console.log("血氧进度", state.bloodOxygen.progress);
	},

	SET_TEMPERATURE(state, temperature) {
		state.temperature = temperature;
	},

	SET_STEP(state, step) {
		state.step = step;
	},

	SET_HISTORY(state, history) {
		state.histories.push(history);
	},

	CLEAR_HISTORIES(state) {
		state.histories = [];
	},

	SET_MEMORY(state, memory) {
		state.memory = Object.assign(state.memory, memory);
	},

	SET_PERIOD(state, period) {
		state.period = period;
	},

	SET_NOTIFY_DATA(state, {
		type,
		data
	}) {
		if (state[type]) {
			state[type] = Object.assign(state[type], data);
		}
	},

	SAVE_HEX_RECORD(state, hex) {
		state.hexArr.push(hex);
	},

	RESET_STATE(st) {
		Object.assign(st, deepClone(state));
	},

	SET_SQLITE_LIST(state, sql) {
		state.sqLiteList.push(sql);
	},

	CLEAR_SQLITE_LIST(state) {
		state.sqLiteList = [];
	},

	SET_SQLITE_ANA_LIST(state, sql) {
		state.sqLiteAnaList.push(sql);
	},

	CLEAR_SQLITE_ANA_LIST(state) {
		state.sqLiteAnaList = [];
	},
};

const actions = {
	setRing({
		commit
	}, ring) {
		commit("SET_RING", ring);
	},
	addNotify(context) {
		context.dispatch(
			"bleManage/addNotifyListener", {
				event: "ringDataManage/receive",
				callback: context.dispatch.bind(context, "ringDataManage/receive"),
			}, {
				root: true
			}
		);
	},

	receive({
		dispatch
	}, data) {
		log4j.log("收到消息 notify", data);
		dispatch("yongXinAnalysis", data);
	},

	notify({
		commit
	}, data) {
		log4j.log("收到回调 notify", data);
		const {
			id,
			cmd,
			sub,
			needAnswer,
			...result
		} = analysis.commonPushResponseAnalysis(data);

		switch (cmd) {
			case 0x12:
				// 电量推送
				commit('SET_NOTIFY_DATA"', {
					type: "battery",
					data: result
				});
				break;

			case 0x31:
				// 心率推送
				commit('SET_NOTIFY_DATA"', {
					type: "heart",
					data: result
				});
				break;

			case 0x32:
				// 血氧推送
				commit('SET_NOTIFY_DATA"', {
					type: "blood",
					data: result
				});
				break;

			case 0x36:
				// 消极响应
				commit('SET_NOTIFY_DATA"', {
					type: "fault",
					data: result
				});
				break;

			default:
				break;
		}
	},

	yongXinAnalysis({
		state,
		commit,
		dispatch
	}, hex) {
		const header = parseInt(hex.slice(4, 6), 16);
		const sub = parseInt(hex.slice(6, 8), 16);
		commit("SAVE_HEX_RECORD", hex);

		commit("SET_SQLITE_LIST", [`'${header}'`, `'${sub}'`, `'${hex}'`, Date.now()]);

		let result;
		switch (header) {
			case 0x10:
				result = analysis.timeGettingAnalysis(hex);

				dispatch("freshTimeout", header);

				console.log("时间", result);
				dispatch("changeQueryIndex");

				if (result.sub === 0x01) {
					commit("SET_TIME", result);
					dispatch("changeProgress", 2);
				} else if (result.sub === 0x00) {
					dispatch("changeProgress", 7);
				}

				break;

			case 0x11:
				result = analysis.wareVersionAnalysis(hex);
				console.log("版本号", result);
				dispatch("freshTimeout", header);

				commit("SET_VERSION", result);
				dispatch("changeQueryIndex");
				dispatch("changeProgress", 3);

				break;
			case 0x12:
				result = analysis.batteryLevelAnalysis(hex);
				console.log("电量", result);
				dispatch("freshTimeout", header);

				commit("SET_BATTERY", result);
				dispatch("changeQueryIndex");
				dispatch("changeProgress", 5);
				break;
			case 0x31:
				result = analysis.testHeartRateHrvAnalysis(hex);
				console.log("心率", result);
				commit("SET_HEARTRATE_HRV_PRESS", result);
				break;

			case 0x32:
				result = analysis.testBloodOxygenAnalysis(hex);
				console.log("血氧", result);
				commit("SET_BLOOD", result);
				break;

			case 0x34:
				result = analysis.testTemperatureAnalysis(hex);
				console.log("温度", result);
				commit("SET_TEMPERATURE", result.temperature);
				break;

			case 0x35:
				result = analysis.realTimeStepAnalysis(hex);
				console.log("步数", result);
				commit("SET_STEP", result.step);
				break;

			case 0x36:
				result = analysis.historyDataOrMemory(hex);
				dispatch("freshTimeout", header);

				console.log("历史数据", result);
				dispatch("changeProgress", 6);

				if (result.total === 0) {
					console.log("🈚️历史数据， 进入⏲");

					new Promise((resolve) => {
						let times = 50;
						let timer = setInterval(() => {
							times--;
							dispatch("changeProgress", ((50 - times) * 100) / times || 1);
							if (times <= 0) {
								clearInterval(timer);
								resolve(true);
							}
						}, times);
					}).then(() => {
						console.log("🈚️历史数据， 下一步");
						dispatch("changeQueryIndex");
						commit("CLEAR_HISTORIES");
					});
					return;
				}

				if (result.sub === 0x00 || result.sub === 0x01) {
					commit("SET_HISTORY", result);
					if (result.total !== 0) {
						const progress = (result.index * 100) / result.total;
						dispatch("changeProgress", progress || 1);
					}
					if (result.finish) {
						log4j.log("历史数据获取完毕 111", (state.histories?.length || 0) + "条");
						console.log(state.histories);

						dispatch("changeQueryIndex");
					}
				} else if (result.sub === 0x04) {
					commit("SET_HISTORY", result);
				}
				break;

			case 0x37:
				result = analysis.periodAnalysis(hex);
				log4j.log("采集周期", result);
				dispatch("freshTimeout", header);

				commit("SET_PERIOD", result.period);
				dispatch("changeQueryIndex");
				dispatch("changeProgress");
				break;

			default:
				break;
		}

		commit("SET_SQLITE_ANA_LIST", [`'${header}'`, `'${sub}'`, Date.now(), `'${JSON.stringify(result)}'`]);
	},

	changeQueryIndex({
		state,
		commit,
		dispatch
	}, index) {
		if (!state.syncLoading) return;
		if (index === undefined) {
			commit("SET_QUERY_INDEX", ++state.queryIndex);
		} else {
			commit("SET_QUERY_INDEX", index);
		}
		dispatch("doQueue");
	},

	changeProgress({
		state,
		commit
	}, progress) {
		const queryIndex = state.queryIndex;
		if (queryIndex <= 5) {
			commit("SET_SYNC_PROGRESS", queryIndex);
		} else {
			commit("SET_SYNC_PROGRESS", Math.min(Math.max(Math.max(queryIndex, progress || 1), state.syncProgress),
				100));
		}
		log4j.log("同步进度", state.syncProgress, "queryIndex", queryIndex);
	},

	syncData({
		dispatch,
		commit
	}) {
		const bind = getWithExpiration("bind");
		commit("SET_SYNC_LOADING", true);
		if (bind && bind == 1) {
			dispatch("changeQueryIndex", 0);
		} else {
			dispatch("changeQueryIndex", 1);
			dispatch("changeProgress", 1);
		}
		log4j.log("开始同步数据");
	},

	stopSyncData({
		commit,
		dispatch
	}) {
		log4j.log("停止同步");
		commit("SET_SYNC_LOADING", false);
		dispatch("changeProgress", 0);
		dispatch("changeQueryIndex", -1);
	},

	async doQueue({
		state,
		commit,
		dispatch
	}) {
		if (!state.syncLoading) return;
		const query = yxQueue[state.queryIndex];
		const ill = yxQueueIll[state.queryIndex];
		if (typeof query === "function") {
			state.receiveTimeout = setTimeout(() => {
				log4j.log("<<<<<<<<<<<<<<<< 超时跳过 >>>>>>>>>>>>>>>>>>>>>>>>>>", state.queryIndex);
				dispatch("changeQueryIndex");
			}, 5000);
			if (ill === "data" && query.length >= 1) {
				const time_list = Object.values(state.lastUpdateTime).filter((item) => !!item);
				if (time_list.length === 0) {
					log4j.log("🙅🏻‍♀️使用ts 获取数据");
					query();
				} else {
					const earliest = Math.min(...time_list.map((item) => dayjs(item).valueOf()));
					log4j.log("使用ts 获取数据", earliest);
					query(earliest / 1000);
					// query();
				}
			} else {
				query();
			}
		} else {
			log4j.log("执行结束操作");
			setWithExpiration("bind", null, 360);
			dispatch("changeProgress", 100);
			await dispatch("uploadSyncData");
			setTimeout(() => {
				commit("SET_SYNC_LOADING", false);
			}, 1000);
		}
	},

	freshTimeout({
		state
	}, info) {
		log4j.log("跳过器", "============ 初始化 跳过器 ===========", info);
		clearTimeout(state.receiveTimeout);
		state.receiveTimeout = null;
	},

	async uploadSyncData({
		state,
		rootState,
		commit
	}) {
		// 同步戒指设备硬件信息
		try {
			if (!state.ring.mac) return;
			saveDeviceInfo({
				mac: state.ring.mac,
				name: state.ring.name,
				battery: state.battery.batteryLevel,
				versionCode: `${uni.getAppBaseInfo().appVersionCode}`,
			});
		} catch (error) {
			log4j.log("同步戒指设备硬件信息", error);
		}

		await SqLiteData.insertDataBatch(state.sqLiteList)
			.then(() => {
				log4j.log("数据插入", "______________ 数据插入完成 SqLiteData");
				commit("CLEAR_SQLITE_LIST");
			})
			.catch((err) => {
				log4j.log("数据插入", "______________ 数据插入失败 SqLiteData", err);
			});
		await SqlLiteAnalysis.insertDataBatch(state.sqLiteAnaList)
			.then(() => {
				log4j.log("数据插入", "______________ 数据插入完成 SqlLiteAnalysis");
				commit("CLEAR_SQLITE_ANA_LIST");
			})
			.catch((err) => {
				log4j.log("数据插入", "______________ 数据插入失败 SqlLiteAnalysis", err);
			});

		// 同步戒指体征数据信息
		try {
			const sysOffsetMinutes = new Date().getTimezoneOffset();
			const offsetMinutes = state.ringTime.timeZone * -60 || sysOffsetMinutes;
			const sleepDataList = state.histories.map(({
				timestamp,
				date,
				sleepType
			}) => {
				return {
					sysOffsetMinutes,
					offsetMinutes,
					yxSleepValue: {
						timestamp,
						date,
						sleepType,
					},
				};
			});

			const height = rootState.userInfo?.height || 0;
			const weight = rootState.userInfo?.weight || 0;
			const sex = rootState.userInfo?.sex || 4;
			const stepLen = getStepLength(height, sex);

			const otherDataList = state.histories.map((his) => {
				const steps = his.stepCount;
				const distance = conversionDistanceBySteps(steps, stepLen);
				const calories = conversionCalorieBySteps(weight || 0, distance, sex);
				return {
					sysOffsetMinutes,
					offsetMinutes,
					heartBeatValue: his.heartRate,
					bloodOxValue: his.bloodOxygen,
					temperatureValue: his.temperature,
					pressValue: his.press,
					hrvValue: his.hrv,
					ts: his.timestamp,
					ringDataDateStr: his.date,
					stepValue: {
						detailMinterStep: his.stepCount,
						calories,
						distance,
					},
				};
			});

			if (sleepDataList.length) {
				console.log("睡眠数据 sleepDataList", sleepDataList);
				await batchSaveRingData(sleepDataList)
					.then((res) => {
						console.log("batchSaveRingData sleepDataList", res);
					})
					.catch((error) => console.log("batchSaveRingData sleepDataList error", error));
			}

			await waiting(100);

			if (otherDataList.length) {
				console.log("其他数据 otherDataList", otherDataList);
				await batchSaveRingData(otherDataList)
					.then((res) => {
						console.log("batchSaveRingData otherDataList", res);
					})
					.catch((error) => console.log("batchSaveRingData otherDataList error", error));
			}
		} catch (error) {
			log4j.log("同步数据错误", error);
		}

		return Promise.resolve(true);
	},

	testHeart() {
		protocol.testHeartRateHrv();
	},

	stopTestHeart() {
		protocol.stopTestHeartRateHrv();
	},

	testBlood() {
		protocol.testBloodOxygen();
	},

	stopTestBlood() {
		protocol.stopTestBloodOxygen();
	},

	factoryReset() {
		// 不恢复出厂  仅删除数据
		protocol.clearHistoryData();
	},
};

export default {
	namespaced: true,
	state: deepClone(state),
	getters,
	mutations,
	actions,
};